#pragma once
#include <string>
#include <map>
#include <stdexcept>

namespace krryn{
namespace parsers{
//! Base class for parsing errors
class parse_error : public std::runtime_error{
public:
	parse_error(const std::string &a_ParseError) : runtime_error(a_ParseError) {}
};

class invalid_entry : public parse_error{
public:
	invalid_entry(const std::string &a_Entry) : parse_error(a_Entry) {}
};

class element_not_found : public parse_error{
public:
	element_not_found(const std::string &a_Element) : parse_error(a_Element) {}
};

class multiple_protos_undefined : public parse_error{
public:
	multiple_protos_undefined(const std::string &a_Element) : parse_error(a_Element) {}
};

class parser_list_node;
// Base class that resolves the prototype
// and implements some of the basics of the language
// All child-classes are required to build their own datastructures
// when parsing is done.
class database_list{
public:
	database_list();

	void load(parser_list_node &a_Root);

protected:
	//! Parsing is done, build the domain specific stuff
	virtual void build(parser_list_node &a_Entry) = 0;

	//! Load reserved words
	virtual void load_reserved() = 0;

	parser_list_node *get_proto_root(parser_list_node *a_Node);
	parser_list_node *get_proto_by_name(const std::string &a_Name);
	parser_list_node *get_element_by_name(const std::string &a_Name, parser_list_node *a_Current = 0);

	std::map<std::string, parser_list_node*> m_Reserved;
private:
	void resolve_prototypes(parser_list_node &a_Node);
	void merge_properties(parser_list_node &a_Node, parser_list_node &a_Prototype);

	parser_list_node *m_Entry;
	parser_list_node *m_Root;
	std::string m_ProtoName;
	std::string m_EntryName;
	std::string m_RootName;
};
}
}